package com.bolt.core.view.freemarker;

import com.bolt.common.utils.SpringContextUtil;
import com.bolt.common.utils.StrUtil;
import com.bolt.core.view.components.ComponentsBase;
import com.bolt.core.view.config.PageRepository;
import com.bolt.core.view.config.UIProperties;
import com.bolt.core.view.templates.FreemarkerTemplateEngine;
import com.bolt.support.freemarker.DirectiveUtil;
import freemarker.core.Environment;
import freemarker.template.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * Created by Administrator on 2019/3/29.
 */
public abstract class TagModel implements TemplateDirectiveModel {


    protected PageRepository getPageRepository() {
        PageRepository pageRepository = SpringContextUtil.getBean(PageRepository.class);
        return pageRepository;
    }

    public abstract ComponentsBase getUI(Map params);


    protected UIProperties getUiProperties() {
        return SpringContextUtil.getBean(UIProperties.class);
    }

    protected FreemarkerTemplateEngine getFreemarkerTemplateEngine() {
        return SpringContextUtil.getBean(FreemarkerTemplateEngine.class);
    }

    protected HttpServletRequest getRequest() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return requestAttributes.getRequest();
    }

    protected HttpServletResponse getResponse() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return requestAttributes.getResponse();
    }

    protected String getTemplate(Map<String, TemplateModel> params) {
        return DirectiveUtil.getString(params, "template");
    }

    protected String getTemplateDir(Map<String, TemplateModel> params) {
        return DirectiveUtil.getString(params, "templateDir");
    }

    protected String getTheme(Map<String, TemplateModel> params) {
        return DirectiveUtil.getString(params, "theme");
    }

    protected void populateParams(ComponentsBase component, Map<String, TemplateModel> params) {
        UIProperties uiProperties = getUiProperties();
        String templateDir = getTemplateDir(params);
        String theme = getTheme(params);
        String template = getTemplate(params);
        if (StrUtil.isNotBlank(templateDir)) {
            component.setTemplateDir(templateDir);
        } else {
            component.setTemplateDir(uiProperties.getDefaultPath());
        }
        if (StrUtil.isNotBlank(theme)) {
            component.setTheme(theme);
        } else {
            component.setTheme(uiProperties.getTheme());
        }
        if (StrUtil.isNotBlank(template)) {
            component.setTemplate(template);
        }
        component.setTemplateEngine(getFreemarkerTemplateEngine());
    }

    @Override
    public void execute(Environment environment, Map params, TemplateModel[] templateModels, TemplateDirectiveBody templateDirectiveBody) throws TemplateException, IOException {
        ComponentsBase component = getUI(params);
        populateParams(component, params);
        render(component, environment, params, templateDirectiveBody);
    }

    public abstract void render(ComponentsBase component, Environment env, Map<String, TemplateModel> params, TemplateDirectiveBody body) throws IOException, TemplateException;

    protected String getStrParam(Map params, String name) {
        Object value = params.get(name);
        if (value instanceof SimpleScalar) {
            return ((SimpleScalar) value).getAsString();
        }
        return null;
    }

    public Object getBenaParam(Map params, String name) {
        Object value = params.get(name);
        if (value instanceof freemarker.ext.beans.BeanModel) {
            return ((freemarker.ext.beans.BeanModel) value).getWrappedObject();
        }
        return null;
    }


    protected void renderBody(Environment env, TemplateDirectiveBody body) throws IOException, TemplateException {
        if (body != null) {
            body.render(env.getOut());
        }
    }
}

 